image.png

  1. View(),没有暴露出来,等于没有,过过过
    1
    2
    3
    4
    5
    6
    7
     /**
    * Non-public constructor for use in testing
    */
    View() {
    mResources = null;
    mRenderNode = RenderNode.create(getClass().getName(), this);
    }

  1. View(Context context),当在代码中创建view时使用,传入一个上下文,使该View运行在其中,并且可以通过这个上下文获取主题、资源等。
    1
    2
    3
    4
    5
    6
    7
    /**
    * Simple constructor to use when creating a view from code.
    *
    * @param context The Context the view is running in, through which it can
    * access the current theme, resources, etc.
    */
    public View(Context context) {...}

  1. 从布局文件xml中填充出来的view使用这个2参的构造函数。
    第1个参数context上文说过了,第2个参数attr包含了在xml中定义的属性,初始化的时候需要把这些属性拿出来用。可以看到这个构造直接调用了一个三参构造。那么继续走
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    /**
    * Constructor that is called when inflating a view from XML. This is called
    * when a view is being constructed from an XML file, supplying attributes
    * that were specified in the XML file. This version uses a default style of
    * 0, so the only attribute values applied are those in the Context's Theme
    * and the given AttributeSet.
    *
    * <p>
    * The method onFinishInflate() will be called after all children have been
    * added.
    *
    * @param context The Context the view is running in, through which it can
    * access the current theme, resources, etc.
    * @param attrs The attributes of the XML tag that is inflating the view.
    * @see #View(Context, AttributeSet, int)
    */
    public View(Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, 0);
    }

  1. 三参构造
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    /**
    * Perform inflation from XML and apply a class-specific base style from a
    * theme attribute. This constructor of View allows subclasses to use their
    * own base style when they are inflating. For example, a Button class's
    * constructor would call this version of the super class constructor and
    * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
    * allows the theme's button style to modify all of the base view attributes
    * (in particular its background) as well as the Button class's attributes.
    *
    * @param context The Context the view is running in, through which it can
    * access the current theme, resources, etc.
    * @param attrs The attributes of the XML tag that is inflating the view.
    * @param defStyleAttr An attribute in the current theme that contains a
    * reference to a style resource that supplies default values for
    * the view. Can be 0 to not look for defaults.
    * @see #View(Context, AttributeSet)
    */
    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    this(context, attrs, defStyleAttr, 0);
    }
    2参构造会调用这个3参构造,多了一个默认样式defStyleAttr,比如Button的构造会传一个Button的样式,然后调用了自己的四参构造
    1
    2
    3
    public Button(Context context, AttributeSet attrs) {
    this(context, attrs, com.android.internal.R.attr.buttonStyle);
    }
    而四参构造会调用父类TextView的四参构造,TextView会继续调用父类View的四参构造。
    1
    2
    3
    public Button(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    }
    所以这个三参构造的第三个参数defStyleAttr是给View的子类传自己用的属性配置的。

  1. 四参构造
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    /**
    * Perform inflation from XML and apply a class-specific base style from a
    * theme attribute or style resource. This constructor of View allows
    * subclasses to use their own base style when they are inflating.
    * <p>
    * When determining the final value of a particular attribute, there are
    * four inputs that come into play:
    * <ol>
    * <li>Any attribute values in the given AttributeSet.
    * <li>The style resource specified in the AttributeSet (named "style").
    * <li>The default style specified by <var>defStyleAttr</var>.
    * <li>The default style specified by <var>defStyleRes</var>.
    * <li>The base values in this theme.
    * </ol>
    * <p>
    * Each of these inputs is considered in-order, with the first listed taking
    * precedence over the following ones. In other words, if in the
    * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
    * , then the button's text will <em>always</em> be black, regardless of
    * what is specified in any of the styles.
    *
    * @param context The Context the view is running in, through which it can
    * access the current theme, resources, etc.
    * @param attrs The attributes of the XML tag that is inflating the view.
    * @param defStyleAttr An attribute in the current theme that contains a
    * reference to a style resource that supplies default values for
    * the view. Can be 0 to not look for defaults.
    * @param defStyleRes A resource identifier of a style resource that
    * supplies default values for the view, used only if
    * defStyleAttr is 0 or can not be found in the theme. Can be 0
    * to not look for defaults.
    * @see #View(Context, AttributeSet, int)
    */
    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    this(context);

    final TypedArray a = context.obtainStyledAttributes(
    attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
    ...
    }

    比三参多了个defStyleRes,子类在覆写构造的时候可以传入样式资源到这里。可以看到,四参构造也是先调用了this(context),然后获取到TypeArray拿各种属性,再继续对view进行初始化操作。

#####总结:View(Context)是从代码中创建view走的构造。 View(Context,AttributeSet),是从xml中填充的view走的构造,2参会调用3参,3参调用4参,4参最后会调用1参,然后拿到所有属性再初始化。这样子类的构造可以传入特定的attr和style来初始化。